package com.iss.yunpan.service.impl;

import com.iss.yunpan.dao.FileDao;
import com.iss.yunpan.dao.FileShareDao;
import com.iss.yunpan.entity.FileContent;
import com.iss.yunpan.entity.Users;
import com.iss.yunpan.service.FileService;
import com.obs.services.IObsClient;
import com.obs.services.ObsClient;
import com.obs.services.model.HttpMethodEnum;
import com.obs.services.model.ObsObject;
import com.obs.services.model.TemporarySignatureRequest;
import com.obs.services.model.TemporarySignatureResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpSession;
import com.obs.services.model.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service//代表业务逻辑，能够帮助我们实例化
public class FileServiceImpl implements FileService {
    @Autowired
    private HttpSession session;

    private String endPoint = "obs.cn-north-4.myhuaweicloud.com";
    private String ak = "KMFTH0TFIBTYIACKPJWT";
    private String sk = "LXPrmCt7N9yoUqzMmp8UppOipxvUPZkRfndWlhA1";
    private String bucketName = "yunpanst";

    @Autowired//依赖注入
    private FileDao dao;

    @Override
    public List<FileContent> getAllFile(String fileName) {
        return dao.getAllFile(fileName);
    }

    @Override
    public boolean checkFileContent(String fileName, Integer parentId) {
        FileContent cont = dao.getFileContentByFileNameAndParentId(fileName, parentId);
        if (cont != null) {
            return true;
        }
        return false;
    }

    @Override
    public void insertFolder(String fileName, Integer parentId) {
        Users user= (Users) session.getAttribute("users");
        if(user!=null&& !"".equals(user.getUserId())){
            FileContent con=new FileContent();
            con.setFileName(fileName);
            con.setParentId(parentId);
            con.setUploadTime(new Date());
            con.setUserId(user.getUserId());
            con.setFileType("文件夹");
            con.setFileAbsolute(fileName);
            dao.insertFile(con);
            ObsClient obsClient = new ObsClient(ak, sk, endPoint);
            obsClient.putObject(bucketName, fileName + '/', new ByteArrayInputStream(new byte[0]));
        }
    }

    /**
     * 如果文件名相同，更新文件；如果文件名不存在，添加文件
     *
     * @param fileName
     * @param input
     * @param parentId
     */
    @Override
    @Transactional
    public void uploadFile(String fileName, InputStream input, String parentId) throws IOException {
        Users user = (Users) session.getAttribute("users");
        if (user != null && !user.getUserId().equals("")) {
            FileContent con = dao.getFileContentByFileNameAndParentId(fileName, Integer.valueOf(parentId));
            if (con != null) {
                con.setFileSize(input.available() + "kb");
                con.setUploadTime(new Date());
                dao.updateFile(con);
            } else {

                FileContent cont = new FileContent();
                cont.setFileName(fileName);
                cont.setFileSize(input.available() + "kb");
                cont.setFileAbsolute(fileName);
                cont.setFileType(fileName.substring(fileName.lastIndexOf("."), fileName.length()));
                cont.setParentId(Integer.valueOf(parentId));
                cont.setUserId(user.getUserId());
                cont.setUploadTime(new Date());

                //创建ObsClient实例
                ObsClient obsClient = new ObsClient(ak, sk, endPoint);
                obsClient.putObject(bucketName, fileName, input);
                String url = signatureUrl(fileName);
                cont.setUrl(url);
                dao.insertFile(cont);
            }

        }
    }

    /**
     * 获得下载路径
     *
     * @return
     */
    public String signatureUrl(String filename) {
        ObsClient obsClient = new ObsClient(ak, sk, endPoint);
        long expireSeconds = 3600L;
        TemporarySignatureRequest request = new TemporarySignatureRequest();
        request.setBucketName(bucketName);
        request.setObjectKey(filename);

        TemporarySignatureResponse response = obsClient.createTemporarySignature(request);
        request.setExpires(600000);
        return response.getSignedUrl();
    }

    @Override
    public byte[] download(String fileAbsolute) {
        try{
            ObsClient obsClient = new ObsClient(ak, sk, endPoint);
            ObsObject obsObject = obsClient.getObject(bucketName, fileAbsolute);// 读取对象内容
            InputStream input = obsObject.getObjectContent();
            byte[] b = new byte[1024];
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            int len;
            while ((len=input.read(b)) != -1){
                bos.write(b, 0, len);
            }
            obsClient.deleteObject(bucketName,fileAbsolute);
            byte[] out =  bos.toByteArray();
            bos.close();
            input.close();
            return out;
        }catch (IOException e){
            e.printStackTrace();
        }
        return null;
    }

    @Autowired
    private FileShareDao dao_share;
    @Override
    public String getFile(String fileAbsolute){

        //将分享数据放入被分享文件列表
        //TODO 目前还没考虑有人连续点击分享的情况，现在如果有人连续点击会造成重复显示，另外分享失效后的显示也还没解决
        FileContent cont = dao.getFileContentByFileAbsolute(fileAbsolute);
        cont.setShareTime(new Date());//设置分享数据时间
        dao_share.insertFile(cont);

        String resultUrl;
        String objectKey = fileAbsolute;
        final ObsClient obsClient = new ObsClient(ak, sk, endPoint);
        TemporarySignatureRequest request = new TemporarySignatureRequest();
        request.setBucketName(bucketName);
        request.setObjectKey(objectKey);
        request.setRequestDate(new Date());
        request.setExpires(5*60); //5分钟有效期
        TemporarySignatureResponse signature = obsClient.createTemporarySignature(request);
        resultUrl = signature.getSignedUrl();
        System.out.println("获取临时URL~Get Temp Url:(preview):转码前url="+resultUrl);
        return resultUrl;
    }

    @Override
    public void deleteFile(String fileName) {
        FileContent con=new FileContent();
        con.setFileName(fileName);
        dao.deleteFile(con);
    }

    @Override
    public void restoreFile(String fileName) {
        FileContent con=new FileContent();
        con.setFileName(fileName);
        dao.restoreFile(con);
    }

    @Override
    public void delete(String fileName,String huiFile) {
        ObsClient obsClient = new ObsClient(ak, sk, endPoint);
        obsClient.deleteObject(bucketName, huiFile);
        FileContent con=new FileContent();
        con.setFileName(fileName);
        dao.delete(con);
    }

    @Override
    public List<FileContent> getAllFile1(String fileName) {
        return dao.getAllFile1(fileName);
    }

    @Override
    public FileContent getFileById(Integer id) {
        return dao.getFileById(id);
    }

    @Override
    public void renameFile(String fileName, String fileAbsolute,Integer id) {

    }
    @Override
    public void checkFileName(Integer id, String newFileName, String newFileAbsolute, String fileAbsolute)throws IOException {
        dao.updateFileName(id,newFileName,newFileAbsolute,fileAbsolute);
        final ObsClient obsClient = new ObsClient(ak, sk, endPoint);
        ObsObject obsObject = obsClient.getObject(bucketName,fileAbsolute);
        System. out .println("Object content:");
        InputStream input = obsObject.getObjectContent();
        byte[] b = new byte[1024];
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        int len;
        while ((len=input.read(b)) != -1){
            bos.write(b, 0, len);
        }
        System. out .println(new String(bos.toByteArray()));
        obsClient.deleteObject(bucketName,fileAbsolute);
        input.close();
        obsClient.putObject(bucketName, newFileName, new ByteArrayInputStream(bos.toByteArray()));
        bos.close();
    }


    @Override
    public void copyFile(String orignPath,String newPath){
        FileContent orign= dao.getFileContentByPath(orignPath);
        if(!orign.getFileType().equals("文件夹")){
            copy(orignPath,newPath);
        }
        else {
            ObsClient obsClient = new ObsClient(ak, sk, endPoint);
            ListObjectsRequest request = new ListObjectsRequest(bucketName);
            request.setPrefix(orignPath + "/");
            ObjectListing result;
            newPath += (newPath.endsWith("/") ? "" : "/");
            do {
                result = obsClient.listObjects(request);
                for (ObsObject obsObject : result.getObjects()) {
                    if (obsObject.getObjectKey().substring((obsObject.getObjectKey().lastIndexOf("/"))).length() < 2) {
                        continue;
                    }
                    if(orignPath.lastIndexOf("/")==-1){
                        if("/".equals(newPath)){
                            newPath=orignPath+"副本/";
                            FileContent temp=dao.getFileContentByPath(newPath);
                            if(temp!=null){
                                insertFolder(orignPath+"副本",orign.getParentId());
                            }
                        }
                    }else if(orignPath.substring(orignPath.lastIndexOf("/")).equals(newPath.substring(newPath.lastIndexOf("/")))){
                        newPath=orignPath+"副本/";
                        FileContent temp=dao.getFileContentByPath(newPath);
                        if(temp!=null){
                            insertFolder(orignPath+"副本",orign.getParentId());
                        }
                    }

                    System.out.println(obsObject.getObjectKey()+"\t"+newPath);
                    copy(obsObject.getObjectKey(),newPath);
                }
                request.setMarker(result.getNextMarker());
            } while (result.isTruncated());
        }
    }

    @Override
    public void copy(String orignPath, String newPath) {
        FileContent con = dao.getFileContentByPath(orignPath);
        String tail=newPath.endsWith("/") ? "" : "/";
        if (!newPath.equals("")) {
            con.setFileAbsolute(newPath + tail + con.getFileName());
        }else{
            con.setFileAbsolute(con.getFileName());
        }
        if(con.getFileAbsolute().equals(orignPath)){
            con.setFileAbsolute(con.getFileName().replace(".","副本."));
            con.setFileName(con.getFileName().replace(".","副本."));
        }
        FileContent cont = dao.getFileContentByPath(newPath);
        con.setParentId(cont==null?0:cont.getId());
        con.setUploadTime(new Date());
        dao.insertFile(con);
        ObsClient obsClient = new ObsClient(ak, sk, endPoint);
        System.out.println(orignPath+'\t'+con.getFileAbsolute());
        CopyObjectResult result = obsClient.copyObject(bucketName, orignPath,
                bucketName, con.getFileAbsolute());
        System.out.println("\t" + result.getEtag()+result.toString());
    }


}
